/* Drew Whitehurst
 * Thesis Development
 *
 * Grow Function for Labeling Images.
 *
 * Some code originally provided by Dr. Mukul Shirvaikar
 * */


#include "growAPI.h"





/* ------------------------ Public Methods ------------------------ */

void i_initGrow(char * growFileName)
{
  
  FILE *fptr;        /* file pointer that holds image */

  printf("Initiating a Grow Sequence...\n");
  
  /* open image */
  if((fptr = fopen(growFileName, "r")) == NULL)
  {
    /* did not open file */
    printf("ERROR IN OPENING FILE\n");
    return;
  }

  /* save name of image */
  strcpy(growImage.name,growFileName);

  /* get first string of file */
  fscanf(fptr,"%s",buf);

  /* checking for correct file format */
  /* TODO: make this account for all .pnm file types */
  if (buf[1] == '1') 
  {
    /* find the end of this row, preventative */
    fscanf(fptr,"%s",buf);
    while (buf[0] != '\n') fscanf(fptr,"%c",&buf[0]);
  }
  else
  {
    printf("ERROR NOT A .pbn FILE\n");
    return;
  }

  /* Get image size */
  fscanf(fptr,"%d %d\n",&(growImage.ncols),&(growImage.nrows));

  /* allocate memory for the pixel matrix */
  growImage.rawImage = growAllocateMatrix(growImage.nrows,growImage.ncols);

  /* load matrix with individual pixel values */
  for(loopCountX = 0; loopCountX < growImage.nrows; loopCountX++)
  {
    
    for(loopCountY = 0; loopCountY < growImage.ncols; loopCountY++)
    {

      /* get next character, since we are working with ascii .pbn file */
      fscanf(fptr,"%c",buf);

      /* filter out carriage return */
      if(0x0A == *buf) fscanf(fptr,"%c",buf);

      /* load matrix with individual characters */
      growImage.rawImage[loopCountX][loopCountY] = *buf;

    }

  }

  /* close file, we don't need it anymore */
  fclose(fptr);

}

void i_printGrowMatrix(void)
{
  int x, y;

  /* loop through 2d array for printing */
  for(x = 0; x < growImage.nrows; x++)
  {
    for(y = 0; y < growImage.ncols; y++)
    {

      /* sniff out white areas of image */
      if('0' == growImage.rawImage[x][y])
      {

        /* white area is printed with an '-', instead of '0' for
         * better visual viewing on terminal */
        printf("- ");

      }
      else
      {

        /* print label associated with black part of image */
        printf("%c ",growImage.rawImage[x][y]);

      }

    }

    printf("\n");

  }

  printf("\n\n");

}


void i_startAutoGrow(GROWDISPLAYTYPE growDisplayType)
{
  
  /* init labels */
  unsigned char labelName = 'A'; 

  /* clear recursive call counter */
  totalGrowRecursiveCall = 0;

  switch (growDisplayType)
  {
    case GROW_NO_DISPLAY:

      /* to be filled out later */
      break;

    case GROW_DISPLAY_END:

      printAnimation = 0;

      break;

    case GROW_DISPLAY_GROW_ANIMATION:

      printAnimation = 1;

      /* to be filled out later */
      break;

    default:

      /* error trap */
      break;

  }

  printf("Starting Grow Sequence...\n");

  /* loop through all pixels in the image */
  for(loopCountX = 0; loopCountX < growImage.nrows; loopCountX++)
  {
    for(loopCountY = 0; loopCountY < growImage.ncols; loopCountY++)
    {

      /* sniffing out black values */
      if('1' == growImage.rawImage[loopCountX][loopCountY])
      {

        /* call the recursive function 'grow', 
         * labelName goes to next letter */
        grow(loopCountX, loopCountY, labelName++);

      }

    }

  }

}

void i_deallocGrow(void)
{
  unsigned int interval;

  for(interval = 0; interval < growImage.nrows; interval++)
  {
    free(growImage.rawImage[interval]);
  }

  free(growImage.rawImage);

}

/* ------------------------ Private Methods ------------------------ */

void grow(int CoordX, int CoordY, int label)
{
 
  int k,l;


  /* label this item */
  growImage.rawImage[CoordX][CoordY] = label;

  /* print everytime if printAnimation is engaged */
  if(printAnimation) printGrowMatrix();

  /* Check in the X direction */
  for (k = CoordX - 1; k <= CoordX + 1 ; k++)
  {

    /* Check in the Y direction */
    for (l = CoordY - 1; l <= CoordY + 1; l++)
    {

      /* Check to See if 'Color' Matches */
      if(growImage.rawImage[k][l] == '1')
      {

        /* tack one on the recursive call counter */
        totalGrowRecursiveCall++;

        /* Recursive Call */
        grow(k, l, label);

      }

    }

  }

}

unsigned char **growAllocateMatrix(int length, int height)
{
   unsigned char **matrix;
   int i;
   
   /* allocate memory for the for the pointers of each row */
   matrix = (unsigned char **)malloc(sizeof(unsigned char *) * length);

   for(i = 0; i < length; i++)
   {
     
     /* allocate memory for the column positions in each row */
     matrix[i]= (unsigned char *) calloc(height, sizeof(unsigned char));

   }

   return(matrix);

}

